home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Python 1.4 / Python 1.4 source / Lib / posixpath.py < prev    next >
Encoding:
Text File  |  1996-08-26  |  7.4 KB  |  313 lines  |  [TEXT/Pyth]

  1. # Module 'posixpath' -- common operations on Posix pathnames.
  2. # Some of this can actually be useful on non-Posix systems too, e.g.
  3. # for manipulation of the pathname component of URLs.
  4. # The "os.path" name is an alias for this module on Posix systems;
  5. # on other systems (e.g. Mac, Windows), os.path provides the same
  6. # operations in a manner specific to that platform, and is an alias
  7. # to another module (e.g. macpath, ntpath).
  8.  
  9. import os
  10. import stat
  11.  
  12.  
  13. # Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
  14. # On MS-DOS this may also turn slashes into backslashes; however, other
  15. # normalizations (such as optimizing '../' away) are not allowed
  16. # (another function should be defined to do that).
  17.  
  18. def normcase(s):
  19.     return s
  20.  
  21.  
  22. # Return wheter a path is absolute.
  23. # Trivial in Posix, harder on the Mac or MS-DOS.
  24.  
  25. def isabs(s):
  26.     return s[:1] == '/'
  27.  
  28.  
  29. # Join two pathnames.
  30. # Ignore the first part if the second part is absolute.
  31. # Insert a '/' unless the first part is empty or already ends in '/'.
  32.  
  33. def join(a, b):
  34.     if b[:1] == '/': return b
  35.     if a == '' or a[-1:] == '/': return a + b
  36.     # Note: join('x', '') returns 'x/'; is this what we want?
  37.     return a + '/' + b
  38.  
  39.  
  40. # Split a path in head (everything up to the last '/') and tail (the
  41. # rest).  If the path ends in '/', tail will be empty.  If there is no
  42. # '/' in the path, head  will be empty.
  43. # Trailing '/'es are stripped from head unless it is the root.
  44.  
  45. def split(p):
  46.     import string
  47.     i = string.rfind(p, '/') + 1
  48.     head, tail = p[:i], p[i:]
  49.     if head and head <> '/'*len(head):
  50.         while head[-1] == '/':
  51.             head = head[:-1]
  52.     return head, tail
  53.  
  54.  
  55. # Split a path in root and extension.
  56. # The extension is everything starting at the last dot in the last
  57. # pathname component; the root is everything before that.
  58. # It is always true that root + ext == p.
  59.  
  60. def splitext(p):
  61.     root, ext = '', ''
  62.     for c in p:
  63.         if c == '/':
  64.             root, ext = root + ext + c, ''
  65.         elif c == '.':
  66.             if ext:
  67.                 root, ext = root + ext, c
  68.             else:
  69.                 ext = c
  70.         elif ext:
  71.             ext = ext + c
  72.         else:
  73.             root = root + c
  74.     return root, ext
  75.  
  76.  
  77. # Split a pathname into a drive specification and the rest of the
  78. # path.  Useful on DOS/Windows/NT; on Unix, the drive is always empty.
  79.  
  80. def splitdrive(p):
  81.     return '', p
  82.  
  83.  
  84. # Return the tail (basename) part of a path.
  85.  
  86. def basename(p):
  87.     return split(p)[1]
  88.  
  89.  
  90. # Return the head (dirname) part of a path.
  91.  
  92. def dirname(p):
  93.     return split(p)[0]
  94.  
  95.  
  96. # Return the longest prefix of all list elements.
  97.  
  98. def commonprefix(m):
  99.     if not m: return ''
  100.     prefix = m[0]
  101.     for item in m:
  102.         for i in range(len(prefix)):
  103.             if prefix[:i+1] <> item[:i+1]:
  104.                 prefix = prefix[:i]
  105.                 if i == 0: return ''
  106.                 break
  107.     return prefix
  108.  
  109.  
  110. # Is a path a symbolic link?
  111. # This will always return false on systems where os.lstat doesn't exist.
  112.  
  113. def islink(path):
  114.     try:
  115.         st = os.lstat(path)
  116.     except (os.error, AttributeError):
  117.         return 0
  118.     return stat.S_ISLNK(st[stat.ST_MODE])
  119.  
  120.  
  121. # Does a path exist?
  122. # This is false for dangling symbolic links.
  123.  
  124. def exists(path):
  125.     try:
  126.         st = os.stat(path)
  127.     except os.error:
  128.         return 0
  129.     return 1
  130.  
  131.  
  132. # Is a path a directory?
  133. # This follows symbolic links, so both islink() and isdir() can be true
  134. # for the same path.
  135.  
  136. def isdir(path):
  137.     try:
  138.         st = os.stat(path)
  139.     except os.error:
  140.         return 0
  141.     return stat.S_ISDIR(st[stat.ST_MODE])
  142.  
  143.  
  144. # Is a path a regular file?
  145. # This follows symbolic links, so both islink() and isfile() can be true
  146. # for the same path.
  147.  
  148. def isfile(path):
  149.     try:
  150.         st = os.stat(path)
  151.     except os.error:
  152.         return 0
  153.     return stat.S_ISREG(st[stat.ST_MODE])
  154.  
  155.  
  156. # Are two filenames really pointing to the same file?
  157.  
  158. def samefile(f1, f2):
  159.     s1 = os.stat(f1)
  160.     s2 = os.stat(f2)
  161.     return samestat(s1, s2)
  162.  
  163.  
  164. # Are two open files really referencing the same file?
  165. # (Not necessarily the same file descriptor!)
  166.  
  167. def sameopenfile(fp1, fp2):
  168.     s1 = os.fstat(fp1)
  169.     s2 = os.fstat(fp2)
  170.     return samestat(s1, s2)
  171.  
  172.  
  173. # Are two stat buffers (obtained from stat, fstat or lstat)
  174. # describing the same file?
  175.  
  176. def samestat(s1, s2):
  177.     return s1[stat.ST_INO] == s2[stat.ST_INO] and \
  178.         s1[stat.ST_DEV] == s2[stat.ST_DEV]
  179.  
  180.  
  181. # Is a path a mount point?
  182. # (Does this work for all UNIXes?  Is it even guaranteed to work by Posix?)
  183.  
  184. def ismount(path):
  185.     try:
  186.         s1 = os.stat(path)
  187.         s2 = os.stat(join(path, '..'))
  188.     except os.error:
  189.         return 0 # It doesn't exist -- so not a mount point :-)
  190.     dev1 = s1[stat.ST_DEV]
  191.     dev2 = s2[stat.ST_DEV]
  192.     if dev1 != dev2:
  193.         return 1        # path/.. on a different device as path
  194.     ino1 = s1[stat.ST_INO]
  195.     ino2 = s2[stat.ST_INO]
  196.     if ino1 == ino2:
  197.         return 1        # path/.. is the same i-node as path
  198.     return 0
  199.  
  200.  
  201. # Directory tree walk.
  202. # For each directory under top (including top itself, but excluding
  203. # '.' and '..'), func(arg, dirname, filenames) is called, where
  204. # dirname is the name of the directory and filenames is the list
  205. # files files (and subdirectories etc.) in the directory.
  206. # The func may modify the filenames list, to implement a filter,
  207. # or to impose a different order of visiting.
  208.  
  209. def walk(top, func, arg):
  210.     try:
  211.         names = os.listdir(top)
  212.     except os.error:
  213.         return
  214.     func(arg, top, names)
  215.     exceptions = ('.', '..')
  216.     for name in names:
  217.         if name not in exceptions:
  218.             name = join(top, name)
  219.             if isdir(name) and not islink(name):
  220.                 walk(name, func, arg)
  221.  
  222.  
  223. # Expand paths beginning with '~' or '~user'.
  224. # '~' means $HOME; '~user' means that user's home directory.
  225. # If the path doesn't begin with '~', or if the user or $HOME is unknown,
  226. # the path is returned unchanged (leaving error reporting to whatever
  227. # function is called with the expanded path as argument).
  228. # See also module 'glob' for expansion of *, ? and [...] in pathnames.
  229. # (A function should also be defined to do full *sh-style environment
  230. # variable expansion.)
  231.  
  232. def expanduser(path):
  233.     if path[:1] <> '~':
  234.         return path
  235.     i, n = 1, len(path)
  236.     while i < n and path[i] <> '/':
  237.         i = i+1
  238.     if i == 1:
  239.         if not os.environ.has_key('HOME'):
  240.             return path
  241.         userhome = os.environ['HOME']
  242.     else:
  243.         import pwd
  244.         try:
  245.             pwent = pwd.getpwnam(path[1:i])
  246.         except KeyError:
  247.             return path
  248.         userhome = pwent[5]
  249.     if userhome[-1:] == '/': i = i+1
  250.     return userhome + path[i:]
  251.  
  252.  
  253. # Expand paths containing shell variable substitutions.
  254. # This expands the forms $variable and ${variable} only.
  255. # Non-existant variables are left unchanged.
  256.  
  257. _varprog = None
  258.  
  259. def expandvars(path):
  260.     global _varprog
  261.     if '$' not in path:
  262.         return path
  263.     if not _varprog:
  264.         import regex
  265.         _varprog = regex.compile('$\([a-zA-Z0-9_]+\|{[^}]*}\)')
  266.     i = 0
  267.     while 1:
  268.         i = _varprog.search(path, i)
  269.         if i < 0:
  270.             break
  271.         name = _varprog.group(1)
  272.         j = i + len(_varprog.group(0))
  273.         if name[:1] == '{' and name[-1:] == '}':
  274.             name = name[1:-1]
  275.         if os.environ.has_key(name):
  276.             tail = path[j:]
  277.             path = path[:i] + os.environ[name]
  278.             i = len(path)
  279.             path = path + tail
  280.         else:
  281.             i = j
  282.     return path
  283.  
  284.  
  285. # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
  286. # It should be understood that this may change the meaning of the path
  287. # if it contains symbolic links!
  288.  
  289. def normpath(path):
  290.     import string
  291.     # Treat initial slashes specially
  292.     slashes = ''
  293.     while path[:1] == '/':
  294.         slashes = slashes + '/'
  295.         path = path[1:]
  296.     comps = string.splitfields(path, '/')
  297.     i = 0
  298.     while i < len(comps):
  299.         if comps[i] == '.':
  300.             del comps[i]
  301.         elif comps[i] == '..' and i > 0 and \
  302.                       comps[i-1] not in ('', '..'):
  303.             del comps[i-1:i+1]
  304.             i = i-1
  305.         elif comps[i] == '' and i > 0 and comps[i-1] <> '':
  306.             del comps[i]
  307.         else:
  308.             i = i+1
  309.     # If the path is now empty, substitute '.'
  310.     if not comps and not slashes:
  311.         comps.append('.')
  312.     return slashes + string.joinfields(comps, '/')
  313.